package com.chhuang.ewcrm.date;

import org.apache.commons.lang3.StringUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

/**
 * 
* @ClassName: DateUtil 
* @Description:  日期格式转换和计算工具
* @author: 黄晨
* @date: 2015-3-25
*
 */
public class DateUtil {

	public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
	public static final String YYYYMMDD_HHMMSS = "yyyyMMdd_HHmmss";
	public static final String YYYYMMDD_HHMM = "yyyyMMdd HHmm";
	public static final String YYYY_MM_DD = "yyyy-MM-dd";
	public static final String YYYY_MM = "yyyy-MM";
	public static final String YYYYMMDD = "yyyyMMdd";
	public static final String YYYYMM = "yyyyMM";
	public static final String YYYY = "yyyy";
	public static final String MM_dd = "MM-dd";
	public static final String MMdd = "MMdd";
	public static final String MM = "MM";
	public static final String HH_mm_ss = "HH:mm:ss";
	public static final String HH_mm = "HH:mm";
	public static final String HHmmss = "HHmmss";
	public static final String HHmm = "HHmm";
	  
	//默认的日期和事件格式及转换
	public static final String DATE_FORMAT = YYYY_MM_DD;
	public static final String TIME_FORMAT = YYYY_MM_DD_HH_MM_SS;
	public static SimpleDateFormat dateFormater = new SimpleDateFormat(DATE_FORMAT);
	public static SimpleDateFormat timeFormater = new SimpleDateFormat(TIME_FORMAT);
	
	/**
	 * 将字符串转换为yyyy-MM-dd格式日期类型
	 * @param dateStr
	 * @return
	 */
	public static Date string2Date(String dateStr) {
		try {
			return dateFormater.parse(dateStr);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 将字符串转换为yyyy-MM-dd HH:mm:ss格式日期类型
	 * @param timeStr
	 * @return
	 */
	public static Date string2Time(String timeStr) {
		try {
			return timeFormater.parse(timeStr);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 将字符串转换为指定格式的日期类型
	 * @param dateStr
	 * @param pattern
	 * @return
	 */
	public static Date string2Date(String dateStr, String pattern) {
		 SimpleDateFormat timeFormater = new SimpleDateFormat(pattern);
		 
		 try {
				return timeFormater.parse(dateStr);
			} catch (ParseException e) {
				e.printStackTrace();
			}
			
		return null;
	}

	/**
	 * 将日期转换为yyyy-MM-dd格式字符串
	 * @param date
	 * @return
	 */
	public static String date2String(Date date) {
		if (date == null) {
			return null;
		}
		return dateFormater.format(date);
	}
	
	/**
	 * 将日期转换为yyyy-MM-dd HH:mm:ss格式字符串
	 * @param date
	 * @return
	 */
	public static String time2String(Date date) {
		if (date == null) {
			return null;
		}
		return timeFormater.format(date);
	}
	
	/**
	 * 将日期按照指定格式转换为相应格式的字符串，如果格式为空，默认为yyyy-MM-dd格式
	 * @param date
	 * @param sFormat
	 * @return
	 */
	public static String date2String(Date date, String sFormat) {
		if (date == null) {
			return null;
		}
		if (StringUtils.isEmpty(sFormat)) {
			sFormat = DATE_FORMAT;
		}
		SimpleDateFormat sdf = new SimpleDateFormat(sFormat);
		return sdf.format(date);
	}
	
	/**
	 * 将时间戳转换为日期+ 00:00:00
	 * @param date
	 * @return
	 */
	public static Date format0Clock(Date date) {
		if (date == null) {
			return null;
		}
		try {
			return timeFormater.parse(date2String(date)+" 00:00:00");
		} catch (ParseException e) {
			e.printStackTrace();
		}
		
		return null;
	}

	/**
	 * 根据给定的字符串长度，自动判断转换为适应的数据格式
	 * @param s
	 * @return
	 */
	public static Date string2DateAuto(String s) {
		if (StringUtils.isEmpty(s)) {
			return null;
		}
		Date result = null;
		try {
			DateFormat format = null;
			if (s.length() > 17)
				format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			else if (s.length() > 15)
				format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
			else if (s.length() > 8)
				format = new SimpleDateFormat("yyyy-MM-dd");
			else if (s.length() > 4)
				format = new SimpleDateFormat("yyyy-MM");
			else {
				format = new SimpleDateFormat("yyyy");
			}
			result = format.parse(s);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 毫秒转日期字符串
	 * @param ms
	 * @param sFormat
	 * @return
	 */
	public static String ms2String(long ms, String sFormat){
		SimpleDateFormat sdf = new SimpleDateFormat(sFormat);
		return sdf.format(ms-TimeZone.getDefault().getRawOffset());
	}
	//---------------------- 以上为日期的基本操作方法
	
	/**
	 * 获取当前时间的yyyy-MM-dd HH:mm:ss格式字符串
	 * @return
	 */
	public static String getNowTime() {
		return time2String(new Date());
	}
	
	/**
	 * 入参是否晚于当前时间
	 * @param dateStr
	 * @return
	 */
	public static boolean afterNow(String dateStr) {
		Date now = new Date();
		Date that = string2Time(dateStr);
		
		if(that == null) {
			return false;
		}
		
		return that.after(now);
	}

	/**
	 * 入参是否晚于当前时间,为空算早于
	 * @param date
	 * @return
	 */
	public static boolean afterNow(Date date) {
		Date now = new Date();
		
		if(date == null) {
			return false;
		}
		
		return date.after(now);
	}
	
	/**
	 * 入参是否早于当前时间,为空也算早于
	 * @param dateStr
	 * @return
	 */
	public static boolean beforeNow(String dateStr) {
		Date now = new Date();
		Date that = string2Time(dateStr);
		
		if(that == null) { //为空也算早于
			return true;
		}
		
		return that.before(now);
	}
	

	/**
	 * 入参是否早于当前时间,为空也算早于
	 * @param date
	 * @return
	 */
	public static boolean beforeNow(Date date) {
		Date now = new Date();
		
		if(date == null) { //为空也算早于
			return true;
		}
		
		return date.before(now);
	}
	
	/**
	 * 判断给定日期相差天数，
	 * @param before
	 * @param after
	 * @return
	 */
	public static int compareDay(Date before, Date after) {
		if(null == before) {
			return -1;
		}
		
		before = string2Date(date2String(before));
		if(after == null) {
			after = new Date();
		}
		
		after = string2Date(date2String(after));

		return Math.round((after.getTime() - before.getTime()) * 1.0f / (1000 * 60 * 60 *24));

	}
	
	/**
	 * 获取当年前几年或者后几年的时间，当年时参数为0，负数指前几年，正数为后几年
	 * @param year
	 * @return
	 */
	public static Date getYear(int year) {
		Calendar c = Calendar.getInstance();
		
		c.set(Calendar.YEAR, c.get(Calendar.YEAR) + year);
		c.set(Calendar.DAY_OF_YEAR, c.getActualMinimum(Calendar.DAY_OF_YEAR));
		
		c.set(Calendar.HOUR_OF_DAY, c.getActualMinimum(Calendar.HOUR_OF_DAY));
		c.set(Calendar.MINUTE, c.getActualMinimum(Calendar.MINUTE));
		c.set(Calendar.SECOND, c.getActualMinimum(Calendar.SECOND));
		
		return c.getTime();
	}
	
	/**
	 * 获取当月前几月或者后几月的时间，当月时参数为0，负数指前几月，正数为后几月
	 * @param month
	 * @return
	 */
	public static Date getMonth(int month) {
		Calendar c = Calendar.getInstance();
		
		c.set(Calendar.MONTH, c.get(Calendar.MONTH) + month);
		c.set(Calendar.DAY_OF_MONTH, c.getActualMinimum(Calendar.DAY_OF_MONTH));
		
		c.set(Calendar.HOUR_OF_DAY, c.getActualMinimum(Calendar.HOUR_OF_DAY));
		c.set(Calendar.MINUTE, c.getActualMinimum(Calendar.MINUTE));
		c.set(Calendar.SECOND, c.getActualMinimum(Calendar.SECOND));
		
		return c.getTime();
	}
	
	/**
	 * 获取当天前几天或者后几天的时间，当天时参数为0，负数指前几天，正数为后几天
	 * @param day
	 * @return
	 */
	public static Date getDay(int day) {
		Calendar c = Calendar.getInstance();
		
		c.set(Calendar.DAY_OF_MONTH, c.get(Calendar.DAY_OF_MONTH) + day);
		
		c.set(Calendar.HOUR_OF_DAY, c.getActualMinimum(Calendar.HOUR_OF_DAY));
		c.set(Calendar.MINUTE, c.getActualMinimum(Calendar.MINUTE));
		c.set(Calendar.SECOND, c.getActualMinimum(Calendar.SECOND));
		
		return c.getTime();
	}
	
	/**
	 * 获取指定日期前几天或者后几天的时间，当天时参数为0，负数指前几天，正数为后几天
	 * @param day
	 * @return
	 */
	public static Date getDay(Date date, int day) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		
		c.set(Calendar.DAY_OF_MONTH, c.get(Calendar.DAY_OF_MONTH) + day);
		
		c.set(Calendar.HOUR_OF_DAY, c.getActualMinimum(Calendar.HOUR_OF_DAY));
		c.set(Calendar.MINUTE, c.getActualMinimum(Calendar.MINUTE));
		c.set(Calendar.SECOND, c.getActualMinimum(Calendar.SECOND));
		
		return c.getTime();
	}
	
	/**
	 * 获取本周前几周或者后几周的时间，本周时参数为0，负数指前几周，正数为后几周
	 * @param week
	 * @return
	 */
	public static Date getWeek(int week) {
		Calendar c = Calendar.getInstance();
		
		c.set(Calendar.WEEK_OF_MONTH, c.get(Calendar.WEEK_OF_MONTH) + week);
		c.set(Calendar.DAY_OF_WEEK, c.getActualMinimum(Calendar.DAY_OF_WEEK));
		
		c.set(Calendar.HOUR_OF_DAY, c.getActualMinimum(Calendar.HOUR_OF_DAY));
		c.set(Calendar.MINUTE, c.getActualMinimum(Calendar.MINUTE));
		c.set(Calendar.SECOND, c.getActualMinimum(Calendar.SECOND));
		
		return c.getTime();
	}
	
	/**
	 * 获取指定日期所在星期的星期一的日期
	 * @param date
	 * @return
	 */
	public static String getWeekStart(Date date){
		DateFormat df = new SimpleDateFormat(YYYY_MM_DD);
		Calendar c = new GregorianCalendar();
		c.setFirstDayOfWeek(Calendar.MONDAY);//设置星期一是第一天
		c.setTime(date);
		c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);//获取星期一
		return df.format(c.getTime());
	}
	
	/**
	 * 获取指定日期所在星期的星期天的日期
	 * @param date
	 * @return
	 */
	public static String getWeekEnd(Date date){
		Calendar c = new GregorianCalendar();
		c.setFirstDayOfWeek(Calendar.MONDAY);//设置星期一是第一天
		c.setTime(date);
		c.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);//获取星期天
		return date2String(c.getTime());
	}
	
	/**
	 * 获取指定日期所在月的第一天
	 * @param date
	 * @return
	 */
	public static String getMonthStart(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.DATE, cal.getActualMinimum(Calendar.DATE));
		Date firstDate = cal.getTime();
		return date2String(firstDate);
	}
	
	/**
	 * 获取指定日期所在月的最后一天
	 * @param date
	 * @return
	 */
	public static String getMonthEnd(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
		Date lastDate = cal.getTime();
		return date2String(lastDate);
	}
	
	/**
	 * 获取指定日期所在年的第一天
	 * @param date
	 * @return
	 */
	public static String getYearStart(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int year = cal.get(Calendar.YEAR);
		return year+"-01-01";
	}
	
	/**
	 * 获取指定日期所在年的最后一天
	 * @param date
	 * @return
	 */
	public static String getYearEnd(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int year = cal.get(Calendar.YEAR);
		return year+"-12-31";
	}

	/**
	 * Date转LocalDateTime
	 * @param date
	 * @return
	 */
	public static LocalDateTime date2LocalDateTime(Date date){
		if(date!=null)
			return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
		else
			return null;
	}


	/**
	 * LocalDateTime转Date
	 * @param localDateTime
	 * @return
	 */
	public static Date localDateTime2Date(LocalDateTime localDateTime){
		if(localDateTime!=null)
			return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
		else
			return null;
	}
}
